home *** CD-ROM | disk | FTP | other *** search
- /* File: HideCalls.c
-
- Description:
- This sample illustrates how the SetHideOnSwitch and GetHideOnSwitch
- routines can be used to hide an application. These routines were first
- documented in Technote TN1102, "Mac OS 8". On the world wide
- web, documentation for these routines can be found at the address:
-
- http://developer.apple.com/technotes/tn/tn1102.html#processmgr
-
- This file contains PowerPC routines that can be used to hide an
- applicaton.
-
- Copyright:
- Copyright © 1999 by Apple Computer, Inc.
- All rights reserved.
-
- Disclaimer:
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Change History (most recent first):
- 12/6/1999 created
- */
-
-
- #include "HideCalls.h"
- #include <MixedMode.h>
- #include <Traps.h>
- #include <Errors.h>
- #include <Gestalt.h>
-
-
-
- /* the following declarations are used on PowerPC computers */
- #if GENERATINGCFM
-
- pascal void SetHideOnSwitch(Boolean setValue) {
- enum {
- uppSetHideOnSwitch = kStackDispatchedPascalStackBased
- | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(unsigned short)))
- | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(unsigned char)))
- };
- CallUniversalProc(GetToolTrapAddress(_OSDispatch), uppSetHideOnSwitch, 0x006BL, setValue);
- }
-
- pascal Boolean GetHideOnSwitch(void) {
- enum {
- uppGetHideOnSwitch = kStackDispatchedPascalStackBased
- | RESULT_SIZE(SIZE_CODE(sizeof(unsigned char)))
- | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(unsigned short)))
- };
- return (Boolean) CallUniversalProc(GetToolTrapAddress(_OSDispatch), uppGetHideOnSwitch, 0x006CL);
- }
-
- #endif
-
-
- /* HideCallsExist returns true if the gestaltHideLayerOnSwitchSupport
- bit is set in the response returned by the gestaltOSAttr Gestalt
- selector. If this routine returns true, then it is safe to call
- SetHideOnSwitch and GetHideOnSwitch. */
- Boolean HideCallsExist(void) {
- long response;
- if (Gestalt(gestaltOSAttr, &response) != noErr) response = 0;
- return ((response & (1<<gestaltHideLayerOnSwitchSupport)) != 0);
- }
-
-
- /* IsFrontProcess returns true in *isFrontP if the process serial number
- in *whichProcess refers to the front most process. IsFrontProcess
- will return an error if an error is returned by the process manager. */
- static OSStatus IsFrontProcess(ProcessSerialNumber *whichProcess, Boolean *isFrontP) {
- ProcessSerialNumber frontPSN;
- OSStatus err;
- /* get the front most process */
- err = GetFrontProcess(&frontPSN);
- if (err != noErr) return err;
- /* check to see if it's the same as *whichProcess */
- err = SameProcess(whichProcess, &frontPSN, isFrontP);
- return err;
-
- }
-
-
-
- /* HideMe hides the current process making it invisible. Calling this routine
- is the same as calling the 'Hide xxxxxx' command from the application
- menu in the top right corner of the screen. HideIdleProc is a routine
- of type EventIdleProc that is called by HideMe while it is waiting for the
- ProcessManager to switch processes in and out of the forground, and
- GetNextP is a routine of type SelectNextFrontProcess that is used by
- HideMe to select the process that is to be moved into the forground
- when it is hidden. */
- OSStatus HideMe(EventIdleProc HideIdleProc, SelectNextFrontProcess GetNextP) {
- ProcessSerialNumber myPSN, targetPSN;
- Boolean isFrontP, switchFlagOn, isSamePSN;
- EventRecord ev;
- OSStatus err;
-
- /* set up locals */
- switchFlagOn = false;
-
- /* verify we are frontmost */
- err = GetCurrentProcess(&myPSN);
- if (err != noErr) goto bail;
-
- /* verify or switch our process in front of all others */
- err = IsFrontProcess(&myPSN, &isFrontP);
- if (err != noErr) goto bail;
- if ( ! isFrontP) {
- /* if it's not the frontmost process, then switch it in */
- err = SetFrontProcess(&myPSN);
- if (err != noErr) goto bail;
- /* wait for it to actually get switched in */
- while (! isFrontP) {
- /* get the next event */
- if ( ! WaitNextEvent(everyEvent, &ev, 0, NULL)) ev.what = nullEvent;
- /* pass it back to the application */
- err = HideIdleProc(&ev);
- if (err != noErr) goto bail;
- /* check if we're in front */
- err = IsFrontProcess(&myPSN, &isFrontP);
- if (err != noErr) goto bail;
- }
- }
-
- /* select the process to switch in */
- err = GetNextP(&myPSN, &targetPSN);
- if (err != noErr) goto bail;
- /* make sure it's not the same process number as ours. */
- err = SameProcess(&myPSN, &targetPSN, &isSamePSN);
- if (err != noErr) goto bail;
- if (isSamePSN) { err = paramErr; goto bail; }
-
- /* turn on the switch and hide flag */
- SetHideOnSwitch(true);
- switchFlagOn = true;
-
- /* switch that process in */
- err = SetFrontProcess(&targetPSN);
- if (err != noErr) goto bail;
- isFrontP = false;
- /* wait for it to get switched in */
- while ( ! isFrontP) {
- /* get the next event */
- if ( ! WaitNextEvent(everyEvent, &ev, 0, NULL)) ev.what = nullEvent;
- /* pass it back to the application */
- err = HideIdleProc(&ev);
- if (err != noErr) goto bail;
- /* check if the next process has been moved in front */
- err = IsFrontProcess(&targetPSN, &isFrontP);
- if (err != noErr) goto bail;
- }
- /* reset the flag */
- SetHideOnSwitch(false);
- switchFlagOn = false;
- /* done */
- return noErr;
-
- bail:
- /* reset the flag if we're aborting */
- if (switchFlagOn) SetHideOnSwitch(false);
- return err;
- }
-